package com.cabal.common.util;

import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * 时间工具类
 * 
 * @author shenkang
 * @date 2019年9月25日 上午11:17:06
 *
 */
@Slf4j
public class DateApiUtil {


	/** 毫秒 */
	public final static long MS = 1;
	/** 每秒钟的毫秒数 */
	public final static long SECOND_MS = MS * 1000;
	/** 每分钟的毫秒数 */
	public final static long MINUTE_MS = SECOND_MS * 60;
	/** 每小时的毫秒数 */
	public final static long HOUR_MS = MINUTE_MS * 60;
	/** 每天的毫秒数 */
	public final static long DAY_MS = HOUR_MS * 24;

	public static final String YYYYMMDD = "yyyyMMdd";

	/** 标准日期格式 */
	public final static String NORM_DATE_PATTERN = "yyyy-MM-dd";
	/** 标准日期格式 */
	public final static String NORM_DATE_CN_PATTERN = "yyyy年MM月dd日";
	/** 标准时间格式 */
	public final static String NORM_TIME_PATTERN = "HH:mm:ss";
	/** 标准日期时间格式 */
	public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

	public final static String NORM_DATETIME_SHORT = "yyyy-MM-dd HH:mm";
	/** 标准日期时间格式 */
	public final static String NORM_DATETIME_T_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";

	public final static String NORM_DATETIME_T_ZZZ_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS";

	public final static String NORM_DATETIME_T_ZZ_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SS";

	public final static String NORM_DATETIME_T_Z_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.S";

	/** HTTP头中日期时间格式 */
	public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z";

	public static final String DATE_TIME_FORMAT_YYYYMMDDHHMISS = "yyyyMMddHHmmss";
	public static final String DATE_TIME_FORMAT_YYYYMMDDHHMISSMI = "yyyyMMddHHmmssSSS";

	public final static String NORM_DATETIME_PATTERN_T = "yyyy/MM/dd HH:mm";

	/** 标准日期（不含时间）格式化器 */
    public final static DateTimeFormatter NORM_DATE_FORMAT = DateTimeFormatter.ofPattern(NORM_DATE_PATTERN);

	/** 标准时间格式化器 */
    public final static DateTimeFormatter NORM_TIME_FORMAT = DateTimeFormatter.ofPattern(NORM_TIME_PATTERN);

	/** 标准日期时间格式化器 */
    public final static DateTimeFormatter NORM_DATETIME_PATTERN_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN);

    public final static DateTimeFormatter NORM_DATETIME_T_PATTERN_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_T_PATTERN);

	public final static DateTimeFormatter NORM_DATETIME_T_ZZZ_PATTERN_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_T_ZZZ_PATTERN);

	public final static DateTimeFormatter NORM_DATETIME_T_ZZ_PATTERN_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_T_ZZ_PATTERN);

	public final static DateTimeFormatter NORM_DATETIME_T_Z_PATTERN_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_T_Z_PATTERN);

    public final static DateTimeFormatter NORM_DATETIME_SHORT_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_SHORT);

    public final static DateTimeFormatter NORM_DATETIME_PATTERN_T_FORMAT = DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN_T);

	/** HTTP日期时间格式化器 */
    public final static DateTimeFormatter HTTP_DATETIME_FORMAT = DateTimeFormatter.ofPattern(HTTP_DATETIME_PATTERN, Locale.US);

	/**
	 * 当前时间，格式 yyyy-MM-dd HH:mm:ss
	 * 
	 * @return 当前时间的标准形式字符串
	 */
	public static String now() {
		return formatDateTime(new Date());
	}

	/**
	 * 当前日期，格式 yyyy-MM-dd
	 * 
	 * @return 当前日期的标准形式字符串
	 */
	public static String today() {
		return formatDate(new Date());
	}

	// ------------------------------------ Format start
	// ----------------------------------------------
	/**
	 * 根据特定格式格式化日期
	 * 
	 * @param date
	 *            被格式化的日期
	 * @param format
	 *            格式
	 * @return 格式化后的字符串
	 */
	public static String format(Date date, String format) {
		return new SimpleDateFormat(format).format(date);
	}

	/**
	 * 格式 yyyy-MM-dd HH:mm:ss
	 * 
	 * @param date
	 *            被格式化的日期
	 * @return 格式化后的日期
	 */
	public static String formatDateTime(Date date) {
		// return format(d, "yyyy-MM-dd HH:mm:ss");
		LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
		return localDateTime.format(NORM_DATETIME_PATTERN_FORMAT);
	}

	/**
	 * 格式化为Http的标准日期格式
	 * 
	 * @param date
	 *            被格式化的日期
	 * @return HTTP标准形式日期字符串
	 */
	public static String formatHttpDate(Date date) {
		// return new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z",
		// Locale.US).format(date);
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
		return localDateTime.format(HTTP_DATETIME_FORMAT);
	}

	/**
	 * 格式 yyyy-MM-dd
	 * 
	 * @param date
	 *            被格式化的日期
	 * @return 格式化后的字符串
	 */
	public static String formatDate(Date date) {
		// return format(d, "yyyy-MM-dd");
		LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
		return localDate.format(NORM_DATE_FORMAT);
	}

	// ------------------------------------ Format end
	// ----------------------------------------------

	// ------------------------------------ Parse start
	// ----------------------------------------------
	/**
	 * 将特定格式的日期转换为Date对象
	 * 
	 * @param dateString
	 *            特定格式的日期
	 * @param format
	 *            格式，例如yyyy-MM-dd
	 * @return 日期对象
	 */
	public static Date parse(String dateString, DateTimeFormatter format) {
		try {
			LocalDateTime localDateTime = LocalDateTime.parse(dateString, format);
			ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
			return Date.from(zonedDateTime.toInstant());
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format " + format
					+ " error!", e);
		}
		return null;
	}

	public static Date parse(String dateString, String format) {
		try {
			LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(format));
			ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
			return Date.from(zonedDateTime.toInstant());
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format " + format
					+ " error!", e);
		}
		return null;
	}

	/**
	 * 格式化String时间
	 *
	 * @param time       String类型时间
	 * @param timeFromat String类型格式
	 * @return 格式化后的Date日期
	 */
	public static Date parseStrToDate(String time, String timeFromat)  {
		if (time == null || time.equals("")) {
			return null;
		}

		Date date = null;
		try {
			DateFormat dateFormat = new SimpleDateFormat(timeFromat);
			date = dateFormat.parse(time);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return date;
	}


	public static Date normParseDate(String dateString) {
		try {
			LocalDate localDate = LocalDate.parse(dateString, NORM_DATE_FORMAT);
			ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
			return Date.from(zonedDateTime.toInstant());
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format " + NORM_DATE_FORMAT.toString()
					+ " error!", e);
		}
		return null;
	}

    public static Date normParseDateTime(String dateString) {
		try {
			LocalDateTime localDateTime = LocalDateTime.parse(dateString, NORM_DATETIME_PATTERN_FORMAT);
			ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
			return Date.from(zonedDateTime.toInstant());
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format " + NORM_DATETIME_PATTERN_FORMAT.toString()
					+ " error!", e);
		}
		return null;
	}

	public static Date normTime(String dateString) {
		try {
			LocalDate localDate = LocalDate.parse(dateString, NORM_TIME_FORMAT);
			ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
			return Date.from(zonedDateTime.toInstant());
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format " + NORM_TIME_FORMAT.toString()
					+ " error!", e);
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd HH:mm:ss
	 * 
	 * @param dateString
	 *            标准形式的时间字符串
	 * @return 日期对象
	 */
	public static Date parseDateTime(String dateString) {
		try {
			if(dateString.contains("T")) {
				if (dateString.length() == 23) {
					return DateApiUtil.parse(dateString, DateApiUtil.NORM_DATETIME_T_ZZZ_PATTERN_FORMAT);
				} else if (dateString.length() == 22) {
					return DateApiUtil.parse(dateString, DateApiUtil.NORM_DATETIME_T_ZZ_PATTERN_FORMAT);
				} else if (dateString.length() == 21) {
					return DateApiUtil.parse(dateString, DateApiUtil.NORM_DATETIME_T_Z_PATTERN_FORMAT);
				} else {
					return DateApiUtil.parse(dateString, DateApiUtil.NORM_DATETIME_T_PATTERN_FORMAT);
				}
			}
			if(dateString.length() == DateApiUtil.NORM_DATETIME_SHORT.length()) {
				return DateApiUtil.parse(dateString, DateApiUtil.NORM_DATETIME_SHORT_FORMAT);
			}
			if(dateString.length() == DateApiUtil.NORM_DATETIME_PATTERN_T.length()) {
				return DateApiUtil.parse(dateString, DateApiUtil.NORM_DATETIME_PATTERN_T_FORMAT);
			}
			return normParseDateTime(dateString);
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format "
					+ NORM_DATETIME_PATTERN_FORMAT.toString() + " error!", e);
		}
		return null;
	}


	/**
	 * 格式yyyy-MM-dd
	 * 
	 * @param dateString
	 *            标准形式的日期字符串
	 * @return 日期对象
	 */
	public static Date parseDate(String dateString) {
		try {
			return normParseDate(dateString);
		} catch (Exception e) {
			log.error("Parse " + dateString + " with format "
					+ NORM_DATE_PATTERN + " error!", e);
		}
		return null;
	}

	/**
	 * 格式HH:mm:ss
	 * 
	 * @param timeString 标准形式的日期字符串
	 * @return 日期对象
	 */
	public static Date parseTime(String timeString) {
		try {
			return normTime(timeString);
		} catch (Exception e) {
			log.error("Parse " + timeString + " with format "
					+ NORM_TIME_PATTERN + " error!", e);
		}
		return null;
	}

	/**
	 * 格式：<br>
	 * 1、yyyy-MM-dd HH:mm:ss<br>
	 * 2、yyyy-MM-dd<br>
	 * 3、HH:mm:ss>
	 * 
	 * @param dateStr
	 *            日期字符串
	 * @return 日期
	 */
	public static Date parse(String dateStr) {
		int length = dateStr.length();
		try {
			if (length == DateApiUtil.NORM_DATETIME_PATTERN.length()) {
				return parseDateTime(dateStr);
			} else if (length == DateApiUtil.NORM_DATE_PATTERN.length()) {
				return parseDate(dateStr);
			} else if (length == DateApiUtil.NORM_TIME_PATTERN.length()) {
				return parseTime(dateStr);
			}
		} catch (Exception e) {
			log.error("Parse " + dateStr + " with format normal error!", e);
		}
		return null;
	}

	// ------------------------------------ Parse end
	// ----------------------------------------------

	// ------------------------------------ Offset start
	// ----------------------------------------------

	/**
	 * 获取指定日期偏移指定时间后的时间
	 * 
	 * @param date
	 *            基准日期
	 * @param calendarField
	 *            偏移的粒度大小（小时、天、月等）使用Calendar中的常数
	 * @param offsite
	 *            偏移量，正数为向后偏移，负数为向前偏移
	 * @return 偏移后的日期
	 */
	public static Date offSiteDate(Date date, int calendarField, int offsite) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(calendarField, offsite);
		return cal.getTime();
	}

	// ------------------------------------ Offset end
	// ----------------------------------------------

	/**
	 * 判断两个日期相差的时长<br/>
	 * 返回 minuend - subtrahend 的差
	 * 
	 * @param subtrahend
	 *            减数日期
	 * @param minuend
	 *            被减数日期
	 * @param diffField
	 *            相差的选项：相差的天、小时
	 * @return 日期差
	 */
	public static long diff(Date subtrahend, Date minuend, long diffField) {
		long diff = minuend.getTime() - subtrahend.getTime();
		return diff / diffField;
	}

	/**
	 * 计时，常用于记录某段代码的执行时间，单位：纳秒
	 * 
	 * @param preTime
	 *            之前记录的时间
	 * @return 时间差，纳秒
	 */
	public static long spendNt(long preTime) {
		return System.nanoTime() - preTime;
	}

	/**
	 * 计时，常用于记录某段代码的执行时间，单位：毫秒
	 * 
	 * @param preTime
	 *            之前记录的时间
	 * @return 时间差，毫秒
	 */
	public static long spendMs(long preTime) {
		return System.currentTimeMillis() - preTime;
	}


	public static Date dateStrTrance(String str){

		SimpleDateFormat simpleDateFormat = null;
		if(str.contains("-") && str.length() == 10){
			simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		}
		if(str.length() == 19){
			simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		}
		if(str.length() == 16){
			simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		}
		if(str.length() == 14){
			simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		}
		if(str.length() == 8){
			simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
		}

		try {
			return simpleDateFormat.parse(str);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static boolean isInTimeRange(LocalTime startTime, LocalTime endTime) {
		// 获取当前时间
		Clock clock = Clock.systemDefaultZone(); // 使用系统默认时区
		LocalDateTime now = LocalDateTime.now(clock);

		// 获取当前时间的时分部分并检查是否在时间段内
		LocalTime currentTime = now.toLocalTime(); // 获取当前时间的时分部分
		boolean isInTimeRange = !currentTime.isBefore(startTime) && currentTime.isBefore(endTime); // 确保不在结束时间之后（如果需要包含结束时间，则使用<=和>=）
		return isInTimeRange;
	}

    public static void main(String[] args) {
    }

}
